import re
import subprocess

from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, \
    QShortcut, QDialog, QFormLayout, QComboBox, QHBoxLayout, QPushButton, QFileDialog
from PyQt5.QtGui import QColor, QPainter, QPixmap, QKeySequence
from PyQt5.QtCore import Qt, QTimer, QPropertyAnimation, QUrl, QRect
from PyQt5.QtWebEngineWidgets import QWebEngineView


class Components(QWidget):

    def __init__(self,
                 my_width,
                 my_height,
                 father_width,
                 father_height,
                 x,
                 y,
                 screen_width=1920,
                 screen_height=1080,
                 parent=None):
        super(Components, self).__init__(parent=parent)
        self.my_wid, self.my_hig = my_width, my_height
        # 组件大小配置初始化
        self.__kWid, self.__kHig = my_width / screen_width, my_height / screen_height
        self.wid, self.hig = int(self.__kWid * father_width), int(self.__kHig * father_height)
        # 组件位置配置初始化
        self.__kX, self.__kY = x / screen_width, y / screen_height
        self.posX, self.posY = int(self.__kX * father_width), int(self.__kY * father_height)
        # 父辈大小记录
        self.fatWid, self.fatHig = father_width, father_height
        # ------------------以上是大小位置配
        self.__InitSize()  # 初始化组件大小

    def __InitSize(self):
        self.setGeometry(self.posX, self.posY, self.wid, self.hig)
        self.setMinimumSize(self.wid, self.hig)

    def updSize(self, wid: int, hig: int):
        if type(wid) != type(hig) != int:
            raise TypeError("父组件的宽高必须是int型")
        # 以下是更新行为
        self.wid, self.hig = int(self.__kWid * wid), int(self.__kHig * hig)
        self.fatWid, self.fatHig = wid, hig
        self.posX, self.posY = int(self.__kX * wid), int(self.__kY * hig)
        self.setGeometry(self.posX, self.posY, self.wid, self.hig)
        self.setMinimumSize(self.wid, self.hig)


class BatWid(QWidget):

    def __init__(self, father_width, father_hight, parent):
        # 电池组件继承
        super(BatWid, self).__init__(parent=parent)
        # 电池组件大小配置初始化
        self.__kWid, self.__kHig = 158 / 1920, 109 / 1080
        self.wid, self.hig = int(self.__kWid * father_width), int(self.__kHig * father_hight)
        # 电池组件坐标配置初始化
        self.__kX, self.__kY = 16 / 1920, 17 / 1080
        self.posX, self.posY = int(self.__kX * father_width), int(self.__kY * father_hight)
        # 父辈大小记录
        self.fatWid, self.fatHig = father_width, father_hight
        # 电池组件位置初始化
        self.setGeometry(self.posX, self.posY, self.wid, self.hig)
        self.setMinimumSize(self.wid, self.hig)
        # 电池组件状态初始化
        self.__batValue = 100
        self.__lastBatValue = 0
        self.__batMode = 0
        self.__lastBatMode = 0
        self.__batPath = "icon/电池电量100.png"
        self.__lastBatPath = ""
        self.__iconVisible = True
        # 电池组件图标定时器
        self.__iconTimer = QTimer()
        self.__iconTimer.timeout.connect(self.__speUpdIcon)
        self.__iconLock = False

        # 创建电池组件总布局
        self.__batGblLay = QVBoxLayout()
        self.__batGblLay.setSpacing(0)
        self.__batGblLay.setContentsMargins(0, 0, 0, 0)
        # 创建电池Icon组件和Text组件
        self.__labelIcon = QLabel()
        self.__labelText = QLabel()
        # 渲染电池Icon组件和Text组件
        self.__initItemIcon()
        self.__initItemText()
        # 将电池Icon组件和Text组件加入到总布局
        self.__batGblLay.addWidget(self.__labelIcon)
        self.__batGblLay.addWidget(self.__labelText)
        self.setLayout(self.__batGblLay)

    def __initItemIcon(self):
        """
        描述：初始化电池图标
        参数：无
        返回值：无
        """
        # 电池Icon组件配置初始化
        self.__kWidIcon, self.__kHigIcon = 158 / 1920, 79 / 1080
        self.widIcon, self.higIcon = int(self.__kWidIcon * self.fatWid), int(self.__kHigIcon * self.fatHig)
        # 渲染电池Icon
        self.__pixIcon = QPixmap(self.__batPath)
        self.__labelIcon.setMaximumSize(self.widIcon, self.higIcon)
        self.__labelIcon.setPixmap(self.__pixIcon)
        self.__labelIcon.setScaledContents(True)

    def __initItemText(self):
        """
        描述：初始化电池文本
        参数：无
        返回值：无
        """
        # 电池Text组件配置初始化
        self.__kWidText, self.__kHigText = 158 / 1920, 30 / 1080
        self.widText, self.higText = int(self.__kWidText * self.fatWid), int(self.__kHigIcon * self.fatHig)
        self.__kFontSize = 30 / 158
        self.fontSize = int(self.__kFontSize * self.widText)
        # 渲染电池Text
        self.__labelText.setMaximumSize(self.widText, self.higText)
        self.__labelText.setTextFormat(Qt.RichText)
        self.__labelText.setText(f"<p style='color:black; text-align:center; font-size:{self.fontSize}px;'>100%<p/>")

    def __updIcon(self):
        """
        描述：更新电池图标
        参数：无
        返回值：无
        """
        # if self.__batPath != self.__lastBatPath:
        #     if self.__batPath != "icon/Battery/电池充电.png":
        #         if self.__batPath != "icon/Battery/电池电量不足.png":
        #             self.__setMode(0)
        #         else:
        #             self.__setMode(2)
        #     self.__lastBatPath = self.__batPath
        #     self.__pixIcon = QPixmap(self.__batPath)
        #     self.__labelIcon.setPixmap(self.__pixIcon)
        self.__pixIcon = QPixmap(self.__batPath)
        self.__labelIcon.setPixmap(self.__pixIcon)

    def __updText(self):
        """
        描述：更新电池文本
        参数：无
        返回值：无
        """
        self.__labelText.setText(
            f"<p style='color:black; text-align:center; font-size:{self.fontSize}px;'>{self.__batValue}%<p/>")
        self.__lastBatValue = self.__batValue

    def __speUpdIcon(self):
        """
        描述：特殊模式更新图标
        参数：无
        返回值：无
        """
        self.__iconVisible = not self.__iconVisible
        self.__labelIcon.setVisible(self.__iconVisible)
        self.__labelText.setVisible(self.__iconVisible)

    def setValue(self, value: float):
        """
        描述：设置当前电池的值
        参数：@value->电池电量[float]
        返回值：无
        """
        # if 0 <= self.__batValue <= 100:
        #     self.__batValue = value
        #     if self.__batMode != 1:
        #         if 87.5 < self.__batValue <= 100:
        #             self.__batPath = "icon/Battery/电池电量100.png"
        #             self.__setMode(0)
        #         elif 75 < self.__batValue <= 87.5:
        #             self.__batPath = "icon/Battery/电池电量 87.5.png"
        #             self.__setMode(0)
        #         elif 50 < self.__batValue <= 75:
        #             self.__batPath = "icon/Battery/电池电量 75.png"
        #             self.__setMode(0)
        #         elif 25 < self.__batValue <= 50:
        #             self.__batPath = "icon/Battery/电池电量 50.png"
        #             self.__setMode(0)
        #         elif 12.5 < self.__batValue <= 25:
        #             self.__batPath = "icon/Battery/电池电量 25.png"
        #             self.__setMode(0)
        #         elif 5 < self.__batValue <= 12.5:
        #             self.__batPath = "icon/Battery/电池电量 12.5.png"
        #             self.__setMode(0)
        #         elif 0 <= self.__batValue <= 5:
        #             self.__batPath = "icon/Battery/电池电量不足.png"
        #             self.__setMode(2)
        #     if self.__batMode == 0:
        #         self.__updIcon()
        #         if self.__iconLock:
        #             self.__iconLock = False
        #             self.__iconTimer.stop()
        #     elif self.__batMode == 2:
        #         if not self.__iconLock:
        #             self.__pixIcon = QPixmap("icon/Battery/电池电量不足.png")
        #             self.__labelIcon.setPixmap(self.__pixIcon)
        #             self.__iconTimer.start(500)
        #             self.__iconLock = True
        #     else:
        #         self.__batPath = "icon/Battery/电池充电.png"
        #         if self.__iconLock:
        #             self.__iconLock = False
        #             self.__iconTimer.stop()
        #         self.__updIcon()
        #     self.__updText()
        # else:
        #     raise ValueError("电池的值的范围超出了")
        if self.__batMode == 0:
            if 0 <= self.__batValue <= 100:
                self.__batValue = value
                if 87.5 < self.__batValue <= 100:
                    self.__batPath = "icon/Battery/电池电量100.png"
                elif 75 < self.__batValue <= 87.5:
                    self.__batPath = "icon/Battery/电池电量 87.5.png"
                elif 50 < self.__batValue <= 75:
                    self.__batPath = "icon/Battery/电池电量 75.png"
                elif 25 < self.__batValue <= 50:
                    self.__batPath = "icon/Battery/电池电量 50.png"
                elif 12.5 < self.__batValue <= 25:
                    self.__batPath = "icon/Battery/电池电量 25.png"
                elif 5 < self.__batValue <= 12.5:
                    self.__batPath = "icon/Battery/电池电量 12.5.png"
                elif 0 <= self.__batValue <= 5:
                    self.__batPath = "icon/Battery/电池电量不足.png"
                self.__updIcon()
                self.__updText()
        elif self.__batMode == 1:
            self.__batPath = "icon/Battery/电池充电.png"
        else:
            raise ValueError("电池的模式不对!")

    def value(self) -> float:
        """
        描述：得到当前电池的值
        参数：无
        返回值：电池电量[float]
        """
        return self.__batValue

    def __setMode(self, modeNum):
        """
        描述：三种电池模式，正常、充电、警告
        参数：无
        返回值：无
        """
        self.__batMode = modeNum

    def mode(self) -> int:
        """
        描述：得到当前的电池模式
        参数：无
        返回值：电池模式[int]->正常[0], 充电[1], 警告[2]
        """
        return self.__batMode

    def setCharge(self, status: bool):
        """
        描述：设置充电状态
        参数：@status->充能状态[bool];
        返回值：无
        """
        if type(status) != bool:
            raise TypeError("充电状态不能为非bool型")
        if status:
            self.__lastBatMode = self.__batMode
            self.__setMode(1)
        else:
            self.__setMode(self.__lastBatMode)

    def updSize(self, wid: int, hig: int):
        """
        描述：更新电池组件的自适应大小
        参数：@wid->父控件的宽度[int]; @hig->父控件的高度[int]
        返回值：无
        """
        if type(wid) != type(hig) != int:
            raise TypeError("父组件的宽高必须是int型")
        # 电池组件的大小
        self.wid, self.hig = int(self.__kWid * wid), int(self.__kHig * hig)
        self.posX, self.posY = int(self.__kX * wid), int(self.__kY * hig)
        self.setGeometry(self.posX, self.posY, self.wid, self.hig)
        self.setMinimumSize(self.wid, self.hig)
        # 电池Icon的大小
        self.widIcon, self.higIcon = int(self.__kWidIcon * wid), int(self.__kHigIcon * hig)
        self.__labelIcon.setMaximumSize(self.widIcon, self.higIcon)
        # 电池文本的大小
        self.widText, self.higText = int(self.__kWidText * wid), int(self.__kHigIcon * hig)
        self.fontSize = int(self.__kFontSize * self.widText)
        self.__labelText.setMaximumSize(self.widText, self.higText)
        self.__labelText.setText(
            f"<p style='color:black; text-align:center; font-size:{self.fontSize}px;'>{self.__batValue}<p/>")


class SignalWid(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=119, my_height=87):
        super(SignalWid, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)

        self.__value = -1
        self.__pixIconPath = [f'icon/Signal/Signal_{index}.png' for index in range(6)]

        self.__myCanvas = QLabel()
        self.__myLayout = QVBoxLayout()

        self.__myPixIcon = QPixmap()

        self.__InitCanvas()
        self.__InitPixIcon()

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)

    def __UpdPixIcon(self, value):
        self.__myPixIcon = QPixmap(self.__pixIconPath[value])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)

    def setValue(self, value: int):
        if value < 0 or value > 5:
            raise ValueError("SignalWid的值没在指定范围内")
        else:
            self.__UpdPixIcon(value)

    def value(self):
        return self.__value


class BackMirror(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=600, my_height=180):
        super(BackMirror, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)

        self.__font_k = 0
        self.__font_size = 0
        self.__lastValue = None
        self.__pixIconPath = ['icon/BackMirror/BackMirror.png']

        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()
        self.__myPixIcon = QPixmap()
        self.__mySecondLayout = QVBoxLayout()
        self.__myTextArea = QLabel()

        self.__InitCanvas()
        self.__InitPixIcon()
        self.__InitTextArea(30, self.wid, self.my_wid)

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.__mySecondLayout.setSpacing(0)
        self.__mySecondLayout.setContentsMargins(0, 30, 0, 0)
        self.__mySecondLayout.addWidget(self.__myTextArea)
        self.__myCanvas.setLayout(self.__mySecondLayout)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)

    def __InitTextArea(self, base_size, root_size, father_size):
        self.__font_k = base_size / father_size
        self.__font_size = int(self.__font_k * root_size)
        font_text = 'D:-100|D:0.01M/s|U:0.02M/s'
        self.__lastValue = font_text
        font_area = f"<p style='text-align:center; font-size:{self.__font_size}px;'>{font_text}<p/>"
        self.__myTextArea.setTextFormat(Qt.RichText)
        self.__myTextArea.setText(font_area)

    def setValue(self, delay: str, down: float, up: float):
        if re.search(r'\d{0,3}', delay) is None:
            raise ValueError("BackMirrorWid的网络值格式错误")
        font_text = f'Ms:{delay}|D:{down}KB/s|U:{up}KB/s'
        self.__lastValue = font_text
        font_area = f"<p style='text-align:center; font-size:{self.__font_size}px;'>{font_text}<p/>"
        self.__myTextArea.setText(font_area)

    def updSize(self, wid: int, hig: int, base_size=30):
        super(BackMirror, self).updSize(wid, hig)
        self.__font_k = base_size / self.my_wid
        self.__font_size = int(self.__font_k * self.wid)
        font_area = f"<p style='text-align:center; font-size:{self.__font_size}px;'>{self.__lastValue}<p/>"
        self.__myTextArea.setText(font_area)
        self.__mySecondLayout.setContentsMargins(0, int(self.__font_size) + 20, 0, 0)


class BackMirrorVideo(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=660, my_height=500):
        super(BackMirrorVideo, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)

        self.__pixIconPath = ['icon/BackMirror/BackMirrorBox.png']
        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()
        self.__myPixIcon = QPixmap()
        self.__mySecondLayout = QVBoxLayout()
        self.myVideoCanvas = QLabel()

        self.__InitCanvas()
        self.__InitPixIcon()
        self.__InitVideoCanvas()
        self.setHidden(True)

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)
        self.__myCanvas.setLayout(self.__mySecondLayout)

    def __InitVideoCanvas(self):
        self.__mySecondLayout.setSpacing(0)
        self.__mySecondLayout.setContentsMargins(20, 20, 20, 20)
        self.__mySecondLayout.addWidget(self.myVideoCanvas)


class SpeedPan_Point(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=74, my_height=13):
        super(SpeedPan_Point, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)

        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()

        self.__pixIconPath = ['icon/SpeedPan/SpeedPanPoint.png']
        self.__InitCanvas()
        self.__InitPixIcon()

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)


class SpeedPan(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=228, my_height=228):
        super(SpeedPan, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)

        self.__pixIconPath = ['icon/SpeedPan/SpeedPan.png']
        self.__lastValue = None

        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()
        self.__myPixIcon = QPixmap()
        self.__mySecondLayout = QVBoxLayout()
        self.__myTextArea = QLabel()

        self.__InitCanvas()
        self.__InitPixIcon()
        self.__InitTextArea(30, self.wid, self.my_wid)

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.__mySecondLayout.setSpacing(0)
        self.__mySecondLayout.setContentsMargins(0, 0, 0, 0)
        self.__mySecondLayout.addWidget(self.__myTextArea)
        self.__myCanvas.setLayout(self.__mySecondLayout)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)

    def __InitTextArea(self, base_size, root_size, father_size):
        self.__font_k = base_size / father_size
        self.__font_size = int(self.__font_k * root_size)
        font_text = '10.1'
        self.__lastValue = font_text
        font_area = f"<p style='text-align:center; font-size:{self.__font_size}px; color: #2fc2ff'>{font_text}<p/>"
        self.__myTextArea.setTextFormat(Qt.RichText)
        self.__myTextArea.setText(font_area)

    def setValue(self, value: float):
        if type(value) != float:
            raise TypeError("SpeedPan的数值类型应该是浮点型")
        self.__lastValue = value
        font_area = f"<p style='text-align:center; font-size:{self.__font_size}px; color: #2fc2ff'>{value}<p/>"
        self.__myTextArea.setText(font_area)

    def updSize(self, wid: int, hig: int, base_size=30):
        super(SpeedPan, self).updSize(wid, hig)
        self.__font_k = base_size / self.my_wid
        self.__font_size = int(self.__font_k * self.wid)
        font_area = f"<p style='text-align:center; font-size:{self.__font_size}px; color: #2fc2ff'>{self.__lastValue}<p/>"
        self.__myTextArea.setText(font_area)


class VideoBox_MicroPhone(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=64, my_height=64):
        super(VideoBox_MicroPhone, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x,
                                                  y=y)
        self.__pixIconPath = ['icon/VideoBox/MicroPhone.png']
        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()
        self.__myPixIcon = QPixmap()

        self.__InitCanvas()
        self.__InitPixIcon()

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)


class VideoBox_Cam(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=64, my_height=64):
        super(VideoBox_Cam, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)
        self.__pixIconPath = ['icon/VideoBox/Cam.png']
        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()
        self.__myPixIcon = QPixmap()

        self.__InitCanvas()
        self.__InitPixIcon()

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)


class VideoBox(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=360, my_height=500):
        super(VideoBox, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)

        self.__pixIconPath = ['icon/VideoBox/Video.png']

        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()
        self.__myPixIcon = QPixmap()
        self.__myMicroPhone = VideoBox_MicroPhone(1800, 600, father_width, father_height, parent=parent)
        self.__myCam = VideoBox_Cam(1600, 600, father_width, father_height, parent=parent)

        self.__InitCanvas()
        self.__InitPixIcon()

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)

    def updSize(self, wid: int, hig: int):
        super(VideoBox, self).updSize(wid, hig)
        self.__myMicroPhone.updSize(wid, hig)
        self.__myCam.updSize(wid, hig)


class MapBox(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=530, my_height=300):
        super(MapBox, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)
        self.__pixIconPath = ['icon/MapBox/Map.png']
        self.__lastGeometry = self.geometry()
        self.__smallStatus = True
        self.__animationStatus = False

        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()
        self.__myPixIcon = QPixmap()
        self.__mySecondLayout = QVBoxLayout()
        self.__myBrowser = QWebEngineView()

        self.__myShortCut = QShortcut(QKeySequence("M"), self)
        self.__myBigAnimation = QPropertyAnimation(self)
        self.__mySmallAnimation = QPropertyAnimation(self)

        self.__InitCanvas()
        self.__InitPixIcon()

        self.__InitBrowser()
        self.__InitShortCut()
        self.__InitBigAnimation()
        self.__InitSmallAnimation()

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.__mySecondLayout.setSpacing(0)
        self.__mySecondLayout.setContentsMargins(15, 15, 15, 15)
        self.__mySecondLayout.addWidget(self.__myBrowser)
        self.__myCanvas.setLayout(self.__mySecondLayout)
        self.setLayout(self.__myLayout)

    def __InitPixIcon(self):
        self.__myPixIcon = QPixmap(self.__pixIconPath[0])
        self.__myCanvas.setPixmap(self.__myPixIcon)
        self.__myCanvas.setScaledContents(True)

    def __InitBrowser(self):
        self.__myBrowser.load(QUrl('http://localhost:8081'))

    def __InitShortCut(self):
        self.__myShortCut.activated.connect(self.__ToBig)
        self.__myShortCut.activated.connect(self.__ToSmall)

    def __InitBigAnimation(self):
        self.__myBigAnimation.setTargetObject(self)
        self.__myBigAnimation.setPropertyName(b'geometry')
        self.__myBigAnimation.setDuration(200)
        self.__myBigAnimation.setLoopCount(1)
        self.__myBigAnimation.setStartValue(self.geometry())
        pointX, pointY = int(self.fatWid * 0.05), int(self.fatHig * 0.05)
        width, height = int(self.fatWid * 0.90), int(self.fatHig * 0.90)
        self.__myBigAnimation.setEndValue(QRect(pointX, pointY, width, height))

    def __InitSmallAnimation(self):
        self.__mySmallAnimation.setTargetObject(self)
        self.__mySmallAnimation.setPropertyName(b'geometry')
        self.__mySmallAnimation.setDuration(200)
        self.__mySmallAnimation.setLoopCount(1)
        self.__mySmallAnimation.setStartValue(self.geometry())
        pointX, pointY = self.posX, self.posY
        width, height = self.wid, self.hig
        self.__mySmallAnimation.setEndValue(QRect(pointX, pointY, width, height))

    def __ToBig(self):
        if self.__smallStatus and not self.__animationStatus:
            print("YES I AM BIG!")
            self.__myBigAnimation.start()
            self.__animationStatus = True
            self.__myBigAnimation.finished.connect(self.__toChangeFalse)

    def __toChangeTrue(self):
        self.__smallStatus = True
        self.__animationStatus = False
        self.__myBigAnimation.setStartValue(self.geometry())

    def __toChangeFalse(self):
        self.__smallStatus = False
        self.__animationStatus = False
        self.__mySmallAnimation.setStartValue(self.geometry())

    def __ToSmall(self):
        if not self.__smallStatus and not self.__animationStatus:
            print("YES I AM SMALL!")
            self.__mySmallAnimation.start()
            self.__animationStatus = True
            self.__mySmallAnimation.finished.connect(self.__toChangeTrue)

    def updSize(self, wid: int, hig: int):
        super(MapBox, self).updSize(wid, hig)
        print("OKOK")
        self.__animationStatus = False
        self.__smallStatus = True
        self.__myBigAnimation.setStartValue(self.geometry())
        pointX, pointY = int(self.fatWid * 0.05), int(self.fatHig * 0.05)
        width, height = int(self.fatWid * 0.90), int(self.fatHig * 0.90)
        self.__myBigAnimation.setEndValue(QRect(pointX, pointY, width, height))
        self.__mySmallAnimation.setStartValue(self.geometry())
        pointX, pointY = self.posX, self.posY
        width, height = self.wid, self.hig
        self.__mySmallAnimation.setEndValue(QRect(pointX, pointY, width, height))


class Helper(Components):

    def __init__(self, x, y, father_width, father_height, parent, my_width=500, my_height=600):
        super(Helper, self).__init__(my_width, my_height, father_width, father_height, parent=parent, x=x, y=y)
        self.__pixIconPath = ['icon/BlackHelper/BlackHelper.jpeg']
        self.__fontTitle_k = 50 / self.my_wid
        self.__fontTitle_size = int(self.__fontTitle_k * self.wid)
        self.__fontText_k = 35 / self.my_wid
        self.__fontText_size = int(self.__fontText_k * self.wid)

        self.__myLayout = QVBoxLayout()
        self.__myCanvas = QLabel()
        # self.__myPixIcon = QPixmap()

        self.__InitCanvas()
        self.__InitItemText()
        # self.setHidden(True)

    def __InitCanvas(self):
        self.__myLayout.setSpacing(0)
        self.__myLayout.setContentsMargins(0, 0, 0, 0)
        self.__myLayout.addWidget(self.__myCanvas)
        self.setLayout(self.__myLayout)

    def __InitItemText(self):
        self.__myCanvas.setTextFormat(Qt.RichText)
        self.__myCanvas.setAlignment(Qt.AlignCenter)
        self.__myCanvas.setText(
            f"""
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontTitle_size}px; color: #FCFCFC;'>《帮助手册》</div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                1.按下【M】开关大地图
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                2.按下【ESC】关闭客户端
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                3.按住【ALT】释放鼠标
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                4.按住【H】开关帮助手册
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                5.按住【TAB】开启后视镜
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                6.按下【F】开关远程图传
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                7.按下【B】开关设置窗口
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                8.按下【V】开关本地图传
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                9.按下【I】增加速度
            </div>
            <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                10.按下【O】减小速度
            </div>
            """
        )

    def updSize(self, wid: int, hig: int):
        super(Helper, self).updSize(wid, hig)
        self.__fontTitle_k = 50 / self.my_wid
        self.__fontTitle_size = int(self.__fontTitle_k * self.wid)
        self.__fontText_k = 35 / self.my_wid
        self.__fontText_size = int(self.__fontText_k * self.wid)
        self.__myCanvas.setText(
            f"""
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontTitle_size}px; color: #FCFCFC;'>《帮助手册》</div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        1.按下【M】开关大地图
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        2.按下【ESC】关闭客户端
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        3.按住【ALT】释放鼠标
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        4.按住【H】开关帮助手册
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        5.按住【TAB】开启后视镜
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        6.按下【F】开关远程图传
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        7.按下【B】开关设置窗口
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        8.按下【V】开关本地图传
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        9.按下【I】增加速度
                    </div>
                    <div style='background-color: #575757; text-align:center; font-size:{self.__fontText_size}px; color: #FCFCFC;' >
                        10.按下【O】减小速度
                    </div>
                    """
        )


class CamWindow(QDialog):

    def __init__(self, parent):
        super(CamWindow, self).__init__(parent=parent)
        self.setWindowTitle("选择输出源")
        self.formLayout = QFormLayout()
        self.HBoxLayout = QHBoxLayout()
        self.setModal(True)

        self.confirmButton = QPushButton("确认")
        self.confirmButton.clicked.connect(self.__onConfirmButtonClicked)
        self.cancelButton = QPushButton("取消")
        self.cancelButton.clicked.connect(self.__onCancelButtonClicked)
        self.fileButton = QPushButton("选择文件")
        self.fileButton.clicked.connect(self.__onfileButtonClicked)

        self.HBoxLayout.addWidget(self.confirmButton)
        self.HBoxLayout.addWidget(self.cancelButton)
        self.HBoxLayout.addWidget(self.fileButton)

        self.selectBox = QComboBox()
        self.formLayout.addRow("选择的视频源：", self.selectBox)
        self.formLayout.addRow(self.HBoxLayout)
        self.setLayout(self.formLayout)
        self.selectFilePath = ''

    def freshCamList(self):
        proc1 = subprocess.Popen("ffmpeg -list_devices true -f dshow -i dummy",
                                 stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, shell=True)
        stdout, stderr = proc1.communicate()
        resList = re.findall(r"\".*Camera\"", stderr.decode())
        self.selectBox.clear()
        for i in resList:
            self.selectBox.addItem(f"摄像头：{i}", userData=('Cam', i, ''))

    def __onConfirmButtonClicked(self):
        typesData, data, path = self.selectBox.currentData()
        if typesData == 'Cam':
            self.parent().SENT_CAMERA = f"ffmpeg -f dshow -r 30 -s 1280x720 -i video={data} -f dshow -i audio=\"麦克风阵列 (Synaptics SmartAudio HD)\" -ac 2 -ar 48000 -b:v 1000k -b:a 500k -sc_threshold 499 -vprofile main -preset ultrafast -tune zerolatency -vcodec h264_amf -f flv rtmp://139.155.181.21/live/03"
        elif typesData == 'File':
            self.parent().SENT_CAMERA = f"ffmpeg -re -i {path} -vcodec copy -acodec copy -f flv rtmp://139.155.181.21/live/03"
        # print(self.parent().SENT_CAMERA)
        self.close()

    def __onCancelButtonClicked(self):
        self.close()

    def __onfileButtonClicked(self):
        # pass
        filePath, fileType = QFileDialog.getOpenFileName(self, "视频文件",
                                                         filter='MP4(*.mp4);;AVI(*.avi);;WMV(*.wmv);;MPEG(*.mpeg);;FLV(*.flv)')
        fileName = filePath.split('/')[-1]
        self.selectBox.addItem(f"文件：{fileName}", userData=('File', fileName, filePath))
